package com.yanggu.jt808.util;

import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;


/**
 * 工具类
 *
 * @Description Jt808Util
 * @Author guoyb
 * @Date 2023/11/6 17:50
 */
@Slf4j
public class Jt808Util {

    /**
     * 根据byteBuf的readerIndex和writerIndex计算校验码
     * 校验码规则：从消息头开始，同后一字节异或，直到校验码前一个字节，占用 1 个字节
     *
     * @param byteBuf
     * @return
     */
    public static byte xorSumBytes(ByteBuf byteBuf) {
        byte sum = byteBuf.getByte(byteBuf.readerIndex());
        for (int i = byteBuf.readerIndex() + 1; i < byteBuf.writerIndex(); i++) {
            sum = (byte) (sum ^ byteBuf.getByte(i));
        }
        return sum;
    }

    public final static int NUMBER_2 = 2;

    /**
     * 验证分包
     *
     * @param bodyProp 消息体属性
     * @return 是否分包
     */
    public boolean hasPackage(byte[] bodyProp) {
        if (bodyProp.length == NUMBER_2) {
            byte buf = (byte) (bodyProp[0] & 0x20);
            return buf != 0;
        } else {
            return false;
        }
    }

    private String getStatusExtAttach(byte[] b) {
        String attachDesc = "扩展车辆信号状态位附加信息：";
        attachDesc += (b[5] & 0x01) == 0 ? "" : "近光灯，";
        attachDesc += (b[5] & 0x02) == 0 ? "" : "远光灯，";
        attachDesc += (b[5] & 0x04) == 0 ? "" : "右转向灯，";
        attachDesc += (b[5] & 0x08) == 0 ? "" : "左转向灯，";
        attachDesc += (b[5] & 0x10) == 0 ? "" : "制动，";
        attachDesc += (b[5] & 0x20) == 0 ? "" : "倒档，";
        attachDesc += (b[5] & 0x40) == 0 ? "" : "雾灯，";
        attachDesc += (b[5] & 0x80) == 0 ? "" : "示廓灯，";
        attachDesc += (b[4] & 0x01) == 0 ? "" : "喇叭，";
        attachDesc += (b[4] & 0x02) == 0 ? "" : "空调，";
        attachDesc += (b[4] & 0x04) == 0 ? "" : "空挡，";
        attachDesc += (b[4] & 0x08) == 0 ? "" : "缓速器，";
        attachDesc += (b[4] & 0x10) == 0 ? "" : "ABS，";
        attachDesc += (b[4] & 0x20) == 0 ? "" : "加热器，";
        attachDesc += (b[4] & 0x40) == 0 ? "" : "离合器，";
        attachDesc += "；";
        return attachDesc;
    }

    /**
     * 获取状态位描述信息
     *
     * @param status 状态位
     * @return 状态位描述
     */
    private String getStatusDesc(byte[] status) {
        String remarkSb = "";
        remarkSb += ((status[3] & 0x01) == 0 ? "ACC关；" : "ACC开；");
        remarkSb += ((status[3] & 0x02) == 0 ? "未定位；" : "定位；");
        remarkSb += ((status[3] & 0x04) == 0 ? "北纬；" : "南纬；");
        remarkSb += ((status[3] & 0x08) == 0 ? "东经；" : "西经；");
        remarkSb += ((status[3] & 0x10) == 0 ? "运营；" : "停运；");
        remarkSb += ((status[3] & 0x20) == 0 ? "经纬度未经保密插件加密；" : "经纬度已经保密插件加密；");
        remarkSb += ((status[2] & 0x03) == 0 ? "空车；" : "");
        remarkSb += ((status[2] & 0x03) == 0x03 ? "满载；" : "");
        // 8位和9位有一点歧义 是8-9一起读 还是9-8一起读
        // 目前按照8-9一起读
        remarkSb += ((status[2] & 0x03) == 0x01 ? "半载；" : "");
        remarkSb += ((status[2] & 0x04) == 0 ? "车辆油路正常；" : "车辆油路断开；");
        remarkSb += ((status[2] & 0x08) == 0 ? "车辆电路正常；" : "车辆电路断开；");
        remarkSb += ((status[2] & 0x10) == 0 ? "车门解锁；" : "车门加锁；");
        remarkSb += ((status[2] & 0x20) == 0 ? "门1（前门）关；" : "门1（前门）开；");
        remarkSb += ((status[2] & 0x40) == 0 ? "门2（中门）关；" : "门2（中门）开；");
        remarkSb += ((status[2] & 0x80) == 0 ? "门3（后门）关；" : "门3（后门）开；");
        remarkSb += ((status[1] & 0x01) == 0 ? "门4（驾驶席门）关；" : "门4（驾驶席门）开；");
        remarkSb += ((status[1] & 0x02) == 0 ? "门5（自定义门）关；" : "门5（自定义门）开；");
        remarkSb += ((status[1] & 0x04) == 0 ? "未使用 GPS 卫星进行定位；" : "使用 GPS 卫星进行定位；");
        remarkSb += ((status[1] & 0x08) == 0 ? "未使用北斗卫星进行定位；" : "使用北斗卫星进行定位；");
        remarkSb += ((status[1] & 0x10) == 0 ? "未使用 GLONASS 卫星进行定位；" : "使用 GLONASS 卫星进行定位；");
        remarkSb += ((status[1] & 0x20) == 0 ? "未使用 Galileo 卫星进行定位；" : "使用 Galileo 卫星进行定位；");
        return remarkSb;
    }


    /**
     * 判断否是 2019 版本 协议
     * 通过版本标识判断
     *
     * @param msgBodyProp 消息体属性
     * @return 是否是2019版本
     */
    public boolean isVersion2019(byte[] msgBodyProp) {
        return (msgBodyProp[0] & 0x40) == 0x40;
    }

    /**
     * 检查是否使用了 ras 加密
     *
     * @param msgBodyProp 消息体属性
     * @return 是否
     */
    public boolean checkRsa(byte[] msgBodyProp) {
        return (msgBodyProp[0] & 0x04) == 0x04;
    }


    public String toGBKString(byte[] data) throws UnsupportedEncodingException {
        return new String(data, "GBK").trim();
    }

    public static String toAsciiString(byte[] data) {
        return new String(data, StandardCharsets.US_ASCII).trim();
    }
}
